/*
* Conditions Of Use
*
* This software was developed by employees of the Sigmatrix(Beijing) Corporation.
* This software is provided by sigmatrix as a service and is expressly
* provided "AS IS."  Sigmatrix MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY.  Sigmatrix does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement.
*
*/
package com.sigmatrix.h5.web.filter;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.jayway.jsonpath.JsonPath;
import com.sigmatrix.h5.annotation.JsonArgument;

/**
 * @ClassName: JsonArgumentResolver
 * @Description: json参数转换实现
 * @author liuzelei
 * @date 2017年6月20日 下午4:32:52
 */
public class JsonArgumentResolver implements HandlerMethodArgumentResolver {
	protected final transient Logger logger = LoggerFactory.getLogger(JsonArgumentResolver.class);

	private static final String JSONBODYATTRIBUTE = "JSON_REQUEST_BODY";

	/**
	 * (non-Javadoc)
	 * 
	 * @Title: supportsParameter
	 * @Description: 
	 * @see org.springframework.web.method.support.HandlerMethodArgumentResolver#supportsParameter(org.springframework.core.MethodParameter)
	 * @author liuzelei
	 * @date 2017年6月20日 下午4:32:52
	 */
	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		return parameter.hasParameterAnnotation(JsonArgument.class);
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @Title: resolveArgument
	 * @Description: 
	 * @see org.springframework.web.method.support.HandlerMethodArgumentResolver#resolveArgument(org.springframework.core.MethodParameter,
	 *      org.springframework.web.method.support.ModelAndViewContainer,
	 *      org.springframework.web.context.request.NativeWebRequest,
	 *      org.springframework.web.bind.support.WebDataBinderFactory)
	 * @author liuzelei
	 * @date 2017年6月20日 下午4:32:52
	 */
	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		final String body = getRequestBody(webRequest);
		if( StringUtils.isBlank(body) || !isJson(body)){
			return null;
		}
		String arg = parameter.getParameterAnnotation(JsonArgument.class).getName();
		if (StringUtils.isEmpty(arg)) {
			arg = parameter.getParameterName();
		}
		return JsonPath.parse(body).read(arg, parameter.getParameterType());
	}
	/**
	 * 
	 *@Title: getRequestBody
	 *@Description: 获取参数信息
	 *@return String
	 *@author liuzelei
	 *@date 2017年6月20日 下午7:27:23
	 *@param webRequest
	 *@return
	 */
	private String getRequestBody(NativeWebRequest webRequest){
        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);

        String jsonBody = (String) webRequest.getAttribute(JSONBODYATTRIBUTE, NativeWebRequest.SCOPE_REQUEST);
        if (jsonBody==null){
            try {
            	final StringWriter stringWriter = new StringWriter();
            	IOUtils.copy(servletRequest.getInputStream(), stringWriter, "utf-8");
				jsonBody = stringWriter.toString();
                webRequest.setAttribute(JSONBODYATTRIBUTE, jsonBody, NativeWebRequest.SCOPE_REQUEST);
            } catch (IOException e) {
            	logger.error("数据转换异常",e);
                return null;
            }
        }
        return jsonBody;
    }
	/**
	 * 
	 *@Title: isJson
	 *@Description: 判断是否是json结构
	 *@return boolean
	 *@author liuzelei
	 *@date 2017年6月20日 下午7:27:16
	 *@param value
	 *@return
	 */
	public static boolean isJson(String value) {
		try {
			JSON.parse(value);
		} catch (JSONException e) {
			return false;
		}
		return true;
	}
}
